package com.qd.pay.service.order;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.CacheKey;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.RedisTemplateUtil;
import com.qd.pay.domain.OrderWxDTO;
import com.qd.pay.model.OrderWx;
import com.qd.pay.repository.OrderWxRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * @author sjk
 */
@Service
@Slf4j
public class OrderWxService {

    private final OrderWxRepository orderWxRepository;
    @Resource
    private RedisTemplateUtil<OrderWx> redisTemplateUtil;

    private static final String PREFIX_ID = "m_order_wx_orderId_{0}";

    @Autowired
    public OrderWxService(OrderWxRepository orderWxRepository) {
        this.orderWxRepository = orderWxRepository;
    }

    @Transactional(rollbackFor = Exception.class)
    public OrderWx save(OrderWx model) throws ApiException {
        try {
            if (!orderWxRepository.save(model)) {
                throw new ApiException(ApiResult.error());
            }
            return model;
        } finally {
            clearCache(model);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(OrderWx model) throws ApiException {
        final OrderWx historyModel = Optional.ofNullable(getById(model.getOrderId())).orElseThrow(() -> new ApiException("ID不存在,不能更新"));
        try {
            if (!orderWxRepository.updateById(model)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean removeById(String orderId) throws ApiException {
        final OrderWx historyModel = Optional.ofNullable(getById(orderId)).orElseThrow(() -> new ApiException("ID不存在,不能删除"));
        try {
            if (!orderWxRepository.removeById(orderId)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    public Boolean isExists(String orderId) {
        return orderWxRepository.isExists(orderId);
    }

    public OrderWx getById(String orderId) {
        String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, orderId);
        return redisTemplateUtil.get(new CacheKey().setKey(key).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY * 3), () -> orderWxRepository.getById(orderId), OrderWx.class);
    }

    public IPage<OrderWxDTO> page(Page<OrderWxDTO> page, OrderWx model) {
        QueryWrapper<OrderWx> queryWrapper = new QueryWrapper<>(model);
        IPage<OrderWx> iPage = orderWxRepository.page(page.convert(this::dtoToModel), queryWrapper);
        return iPage.convert(this::modelToDto);
    }


    private void clearCache(OrderWx model) {
        if (null == model) {
            return;
        }
        String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getOrderId());
        redisTemplateUtil.deleteByKey(key);
    }

    public OrderWxDTO modelToDto(OrderWx model) {
        if (null == model) {
            return null;
        }
        OrderWxDTO dto = new OrderWxDTO();
        dto.setOrderId(model.getOrderId());
        dto.setMchId(model.getMchId());
        dto.setDeviceInfo(model.getDeviceInfo());
        dto.setNonceStr(model.getNonceStr());
        dto.setSign(model.getSign());
        dto.setSignType(model.getSignType());
        dto.setTradeType(model.getTradeType());
        dto.setBankType(model.getBankType());
        dto.setOpenid(model.getOpenid());
        dto.setWxorgid(model.getWxorgid());
        dto.setWxAccountType(model.getWxAccountType());
        model.freeData();
        return dto;
    }

    public OrderWx dtoToModel(OrderWxDTO dto) {
        if (null == dto) {
            return null;
        }
        OrderWx model = new OrderWx();
        model.setOrderId(dto.getOrderId());
        model.setMchId(dto.getMchId());
        model.setDeviceInfo(dto.getDeviceInfo());
        model.setNonceStr(dto.getNonceStr());
        model.setSign(dto.getSign());
        model.setSignType(dto.getSignType());
        model.setTradeType(dto.getTradeType());
        model.setBankType(dto.getBankType());
        model.setOpenid(dto.getOpenid());
        model.setWxorgid(dto.getWxorgid());
        model.setWxAccountType(dto.getWxAccountType());
        dto.freeData();
        return model;
    }

}